# 使用装饰器来为斐波那契函数添加缓存

def cache_demo(func):                           # 定义缓存，以函数为参数（func：功能）
    cache = {}                                  # 将空字典赋值给cache

    def wrapper(*args, **kwargs):               # 定义封装\*args 用来将参数打包成tuple给函数体调用\ **kwargs 打包关键字参数成dict给函数体调用
        res = cache.get(args[0])                # 将args元组中0位的值作为键，通过get函数查找该键在cache字典中对应键的值，然后将该值赋值给res
        if res is None:                         # 判断res是否为空，空则为其赋值
            res = func(*args, **kwargs)
            cache[args[0]] = res
        return res                              # 返回res

    return wrapper


@cache_demo                                                         # 通过@关键字实现装饰器功能
def fib_with_recursion(n):                                          # 定义斐波那契函数
    if n < 2:                                                       # 条件
        return n                                                    # 返回值
    return fib_with_recursion(n - 1) + fib_with_recursion(n - 2)    # 递归


def test_generator():                                               # 定义测试生成器
    for item in [1, 2, 3, 4, 5]:                                    # 遍历[1, 2, 3, 4, 5]并赋值给item
        yield item                                                  # 通过yield将item转化成生成器，使其实现缓存功能
        print('test')


x = int(input('请输入一个>0的整数（查询位数）:'))-1                       # 输入需要查询的位数
y = x+1                                                             # 程序位数内部转换
print('第', y, '位斐波那契数如下')
print(f'\nF(y)={fib_with_recursion(x)}')                            # 打印查询对应位数的斐波那契数值

# 默写迭代器和生成器的概念


# 迭代器
print('迭代器：一个未知长度的数据流，可以通过iter创建迭代器，通过next获取下一个迭代器的元素')
print('迭代器演示__________')
list = [1, 2, 3, 4]
it = iter(list)                                                     # 将list转换位迭代器
print(next(it))                                                     # 通过next函数获取下一个迭代器的元素
print(next(it))
print(next(it))
print('生成器：一种通过yield函数实现惰性延迟的特殊迭代器')
print('生成器演示__________')
g = test_generator()
while True:                                                         # 循环执行
    try:                                                            # 无误则执行获取下一个元素
        print(next(g), end=' ')
    except StopIteration:                                           # 异常
        break
